package teamPL.`trait`

import geotrellis.raster._
import geotrellis.spark._
import geotrellis.spark.io._
import akka.actor._
import akka.event.LoggingAdapter
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.Materializer
import geotrellis.raster.render.{ColorMap, ColorRamp, ColorRamps, Png}
import teamPL.MainSpark
import teamPL.utils.RenderColorMap

import scala.concurrent.{ExecutionContextExecutor, Future}

trait ServiceSpark {
  implicit val system: ActorSystem
  implicit def executor: ExecutionContextExecutor
  implicit val materializer: Materializer

  val logger: LoggingAdapter
  // val colorRender: ColorRamp = ColorRamps.LightToDarkSunset
  val colorRender: ColorMap = RenderColorMap.rgbColorMap

  //  执行渲染
  def pngAsHttpResponse(png: Png): HttpResponse =
    HttpResponse(entity = HttpEntity(ContentType(MediaTypes.`image/png`), png.bytes))

  def root: Route =
    pathPrefix(IntNumber / IntNumber / IntNumber) {
      (zoom, x, y) =>
      complete {
        Future {
          val tileOpt: Option[MultibandTile] =
            try {
              val landsatId: LayerId = LayerId("landsat", zoom)
              val readValue: Reader[SpatialKey, MultibandTile] = MainSpark.reader(landsatId)

              val arrayTile = readValue.read(x, y)

              Some(arrayTile)
            } catch {
              case _: ValueNotFoundError =>
                None
            }

          tileOpt.map { tile =>
            var (redmin,redmax) = tile.band(2).findMinMaxDouble
            var (greenmin,greenmax) = tile.band(1).findMinMaxDouble
            var (bluemin,bluemax) = tile.band(0).findMinMaxDouble

            val red = tile.band(2).normalize(redmin,redmax,0,255).convert(ByteConstantNoDataCellType)
            val green = tile.band(1).normalize(greenmin,greenmax,0,255).convert(ByteConstantNoDataCellType)
            val blue = tile.band(0).normalize(bluemin,bluemax,0,255).convert(ByteConstantNoDataCellType)

            val opacity = red.combine(green){(pRed,pGreen) => {
              if(pRed == 255 && pGreen == 255){
                0
              }else{
                255
              }
            }}.combine(blue){(pCom,pBlue) => {
              if(pCom == 0 && pBlue == 255){
                0
              }else{
                255
              }
            }}

            val aBand = opacity.convert(ByteConstantNoDataCellType)

            val multiTile = MultibandTile(red,green,blue,aBand)

            val colorTile = multiTile.color()
            val rgbaPng = colorTile.renderPng()

            // Render as a PNG
            // val png = tile.renderPng()
            pngAsHttpResponse(rgbaPng)
          }
        }
      }
    } ~
      //  并不确认是否有作用
      pathEndOrSingleSlash {
        getFromFile("static/index.html")
      } ~
      //  并不确认是否有作用
      pathPrefix("") {
        getFromDirectory("static")
      }
}

